#include "StdAfx.h"
#include "Helpers.h"
#include "TestUtils.h"
#include "BreakAndRefillGroupAlgorithm.h"
#include "Group.h"
#include "Graph.h"
#include <math.h>

//using TestUtils;
//extern CreateVertexDirectory;

TestUtils::TestResult BreakGroupWithTemporaryDir(int n, int w)
{
	// Scenario: creates graph over vertices of length n, weight w 
	// creates an empty group and tries to fill it
	// all operations run on copies. So the static directory shouldn't change
	
	TestUtils::CreateVertexDirectory(n,w);
	map<vector<bool>, Vertex*>* vertices = VertexDirectory::GetStaticCopyVertices();
	VertexDirectory* dir = new VertexDirectory(vertices);
	Graph* graph = TestUtils::CreateGraphFromDirectory(vertices, dir);
	Group group(0, dir);
	
	//  try to fill the group - and then make sure the vertex directory wasn't changed
	// can only add one vertex: 0011
	// no size limitations for the group
	BreakAndRefillGroupAlgorithm::BreakAndRefill(*graph, group, 2, 50, 50, 100, 4, dir);
	//validate results:
	//check the static directory is unchanged & the group does contain vertices..
	if (TestUtils::VerifyIsTrue(group.Size() > 0,"The group is empty") == TestUtils::TestFailed)
	{
		delete graph;
		delete dir;
		return TestUtils::TestFailed;
	}

	map<vector<bool>, Vertex*>::iterator it;
	for (it = vertices->begin(); it != vertices->end(); it++)
	{
		Vertex* v = VertexDirectory::GetStaticCopyVertex((*it).second->Name());
		if (TestUtils::VerifyIsTrue(v->IsInGraph() == true,"Static Vertex Directory was changed!") == TestUtils::TestFailed)
		{
			delete graph;
			delete dir;
			return TestUtils::TestFailed;
		}
	}
	
	delete graph;
	delete dir;
	return TestUtils::TestPassed;
}

// Run the BreakAndRefill algorithm on a group, keeping breakPercent of it
TestUtils::TestResult BreakGroupIn6On2Graph(int breakPercent)
{
	// Scenario: creates graph over vertices of length 6, weight 2
	// creates a group with 110000, 001100, 000011, in this order
	// break the group, keeping ~breakPercent of its vertices (actually the largest number of
	// vertices which is no greater then breakPercent of the group)
	
	TestUtils::CreateVertexDirectory(6,2);
	// when looking for couples to add to a group, we don't want the graph to go over 
	// more than 40 couples..
	Group group(0);
	Graph* graph = TestUtils::CreateGroupAndGraph6On2(group);
	int originalGroupSize = group.Size();
	int numberOfVertices2Keep = (int)floor(double(originalGroupSize * breakPercent) / 100);
	// get the vertices in the group, so we can later check they are still in the group
	// we get the names in the order the vertices were added to the group
	list<vector<bool> > vertices = group.VerticesNames();
	
	//try to fill the group with no size limitations for the group
	BreakAndRefillGroupAlgorithm::BreakAndRefill(*graph, group, 2, breakPercent
												, 50, 100, 4, NULL);
	
	// validate results: 
	// validate the group size is at least the same as before
	if (TestUtils::VerifyIsTrue(group.Size() >= originalGroupSize,"The group isn't of the right size") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	//validate the group is still independent
	if (TestUtils::VerifyIsTrue(Algorithms::ValidateGroupIsIndependent(&group),"The group isn't independent") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	//validate that the vertices that were supposed to be in the group are indeed in it
	list<vector<bool> >::iterator it = vertices.begin();
	for (int i = 0; i < numberOfVertices2Keep; i++)
	{
		string message = "The group doesn't contain vertex ";
		message += TestUtils::GetVertexName(*it);
		if (TestUtils::VerifyIsTrue(group.IsVertexInGroup(*it),message) == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
		it++;
	}
	
	// check that the directory was updated correctly: All vertices in the graph appear in the graph. All vertices
	// in the group point to the right group.
	if (Algorithms::ValidateVertexDirectoryState(graph, &group) == false)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}

TestUtils::TestResult BreakGroupIn6On2GraphWithoutImprovement()
{
	// Scenario: creates graph over vertices of length 6, weight 2
	// creates a group with 110000, 001100, 000011, in this order
	// break the group, keeping 50% of its vertices (one vertex)
	// shouldn't be able to improve the group, because it was maximal to begin with
	// should return original group
	
	TestUtils::CreateVertexDirectory(6,2);
	int breakPercent = 50;
	// when looking for couples to add to a group, we don't want the graph to go over 
	// more than 40 couples..
	Group group(0);
	Graph* graph = TestUtils::CreateMaximalGroupAndGraph6On2(group);
	// get the vertices in the group, so we can later check they are still in the group
	list<vector<bool> > vertices = group.VerticesNames();
	
	//try to fill the group with no size limitations for the group
	BreakAndRefillGroupAlgorithm::BreakAndRefill(*graph, group, 2, breakPercent
												, 50, 100, 4, NULL);
	
	// validate resuils: make sure the group wan't changed
	// validate the group size
	if (TestUtils::VerifyIsTrue(group.Size() == 3,"The group isn't of the right size") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	// validate the group wasn't changed: that it contains the same vertices as before 
	list<vector<bool> >::iterator it;
	for (it = vertices.begin(); it != vertices.end(); it++)
	{
		string message = "The group doesn't contain vertex ";
		message += TestUtils::GetVertexName(*it);
		if (TestUtils::VerifyIsTrue(group.IsVertexInGroup(*it), message) == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}
	
	// check that the directory was updated correctly: All vertices in the graph appear in the graph. All vertices
	// in the group point to the right group.
	if (Algorithms::ValidateVertexDirectoryState(graph, &group) == false)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}

TestUtils::TestResult BreakGroupIn6On2GraphWithoutBreaking()
{
	// Scenario: creates graph over vertices of length 6, weight 2
	// creates a group with 110000, 001100, in this order
	// break the group, keeping 100% of its vertices (2 vertices)
	// should be able to add only 1 vertex: 000011
	
	TestUtils::CreateVertexDirectory(6,2);
	int breakPercent = 100;
	// when looking for couples to add to a group, we don't want the graph to go over 
	// more than 40 couples..
	Group group(0);
	Graph* graph = TestUtils::CreateGroupAndGraph6On2(group);
	// get the vertices in the group, these are the vertices that should be in the group in the end
	list<vector<bool> > vertices = group.VerticesNames();
	
	//try to fill the group with no size limitations for the group
	BreakAndRefillGroupAlgorithm::BreakAndRefill(*graph, group, 3, breakPercent, 50, 100, 4, NULL);
	
	// validate resuils: make sure the group wan't changed
	// validate the group size
	if (TestUtils::VerifyIsTrue(group.Size() == 3,"The group isn't of the right size") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	// validate the group wasn't changed: that it contains the same vertices as before 
	list<vector<bool> >::iterator it;
	for (it = vertices.begin(); it != vertices.end(); it++)
	{
		string message = "The group doesn't contain vertex ";
		message += TestUtils::GetVertexName(*it);
		if (TestUtils::VerifyIsTrue(group.IsVertexInGroup(*it), message) == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
	}
	
	// check that the directory was updated correctly: All vertices in the graph appear in the graph. All vertices
	// in the group point to the right group.
	if (Algorithms::ValidateVertexDirectoryState(graph, &group) == false)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}

//OLD CODE - FOR LIMITING THE SIZE OF THE TARGET GROUP IN BREAK&REFILL. NOT SUPPORTED IN THE
// CODE RIGHT NOW
#if 0
// Written as helper function for BreakGroupIn6On2GraphWithSizeLimitation, but may be used seperately
// breakes the group keeping breakPercent of the vertices, and tries to fill the group, but without
// passing the size limitation
// Note: if groupSizeLimitation < group.size() (the limitation < original group size) the test
// will automatically FAIL
TestUtils::TestResult BreakGroupIn6On2GraphWithSizeLimitation(int breakPercent, int groupSizeLimitation, Group& group, Graph* graph)
{
	//if (groupSizeLimitation < )
	int originalGroupSize = group.size();
	int numberOfVertices2Keep = (int)floor(double(originalGroupSize * breakPercent) / 100);
	// get the vertices in the group, so we can later check they are still in the group
	// we get the names in the order the vertices were added to the group
	list<vector<bool> > vertices = group.VerticesNames();
	
	//try to fill the group with size limitation
	BreakAndRefillGroupAlgorithm::BreakAndRefill(*graph, group, groupSizeLimitation, 2, breakPercent
												, 50, 100, 4);
	
	// validate results: 
	// validate the group size is at least the same as before
	if (TestUtils::VerifyIsTrue(group.size() <= groupSizeLimitation,"The group isn't of the right size") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	//validate the group is still independent
	if (TestUtils::VerifyIsTrue(TestUtils::ValidateGroupIsIndependent(&group),"The group isn't independent") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	//validate that the vertices that were supposed to be in the group are indeed in it
	list<vector<bool> >::iterator it = vertices.begin();
	for (int i = 0; i < numberOfVertices2Keep; i++)
	{
		string message = "The group doesn't contain vertex ";
		message += TestUtils::GetVertexName(*it);
		if (TestUtils::VerifyIsTrue(group.isVertexInGroup(*it),message) == TestUtils::TestFailed)
		{
			return TestUtils::TestFailed;
		}
		it++;
	}
	
	// check that the directory was updated correctly: All vertices in the graph appear in the graph. All vertices
	// in the group point to the right group.
	if (Algorithms::ValidateVertexDirectoryState(graph, &group) == false)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}



// Scenario: check break&fill group with limitation on destination group size
// creates graph over vertices of length 6, weight 2
// creates a group with 110000, "break" it (first let it not contain any vertices, 
// then contain all vertices). Fill with limitation of 2
// creates a group with 110000, "break" it (first let it not contain any vertices, 
// then contain all vertices). Fill with limitation of 1
// creates a group with 110000, 001100 break it & fill with limitation of 2
TestUtils::TestResult BreakGroupIn6On2GraphWithSizeLimitation()
{
	TestUtils::CreateVertexDirectory(6,2);
	// when looking for couples to add to a group, we don't want the graph to go over 
	// more than 40 couples..
	Group group1(0);
	Graph* graph = TestUtils::CreateMinimalGroupAndGraph6On2(group1);
	if (BreakGroupIn6On2GraphWithSizeLimitation(0,2,group1, graph) == TestUtils::TestFailed)
	{
		Debug::PrintDebugMsg("Trying to fill a group with 110000, without keeping its original vertex and with size limitation of 2 failed.");
		delete graph;
		return TestUtils::TestFailed;
	}
	
	VertexDirectory::Clear();
	delete(graph);
	Group group2(0);
	graph = TestUtils::CreateMinimalGroupAndGraph6On2(group2);
	if (BreakGroupIn6On2GraphWithSizeLimitation(100,2,group2, graph) == TestUtils::TestFailed)
	{
		Debug::PrintDebugMsg("Trying to fill a group with 110000, keeping original vertex and with size limitation of 2 failed.");
		delete graph;
		return TestUtils::TestFailed;
	}

	VertexDirectory::Clear();
	delete(graph);
	Group group3(0);
	graph = TestUtils::CreateGroupAndGraph6On2(group3);
	if (BreakGroupIn6On2GraphWithSizeLimitation(60,2,group3, graph) == TestUtils::TestFailed)
	{
		Debug::PrintDebugMsg("Trying to fill a group with 110000, 001100, keeping only 110000, and with size limitation of 2 failed.");
		delete graph;
		return TestUtils::TestFailed;
	}

	VertexDirectory::Clear();
	delete(graph);
	Group group4(0);
	graph = TestUtils::CreateGroupAndGraph6On2(group4);
	if (BreakGroupIn6On2GraphWithSizeLimitation(100,2,group4, graph) == TestUtils::TestFailed)
	{
		Debug::PrintDebugMsg("Trying to fill a group with 110000, 001100, keeping all its original vertices and with size limitation of 2 failed.");
		delete graph;
		return TestUtils::TestFailed;
	}

	VertexDirectory::Clear();
	delete(graph);
	Group group5(0);
	graph = TestUtils::CreateMinimalGroupAndGraph6On2(group5);
	if (BreakGroupIn6On2GraphWithSizeLimitation(100,1,group5, graph) == TestUtils::TestFailed)
	{
		Debug::PrintDebugMsg("Trying to fill a group with 110000, keeping its original vertex and with size limitation of 1 failed.");
		delete graph;
		return TestUtils::TestFailed;
	}

	VertexDirectory::Clear();
	delete(graph);
	Group group6(0);
	graph = TestUtils::CreateMinimalGroupAndGraph6On2(group6);
	if (BreakGroupIn6On2GraphWithSizeLimitation(0,1,group6, graph) == TestUtils::TestFailed)
	{
		Debug::PrintDebugMsg("Trying to fill a group with 110000, without keeping its original vertex and with size limitation of 1 failed.");
		delete graph;
		return TestUtils::TestFailed;
	}

	delete graph;
	return TestUtils::TestPassed;
}
#endif


